package org.pz;

import lombok.extern.slf4j.Slf4j;
import org.pz.config.YamlPropertySourceFactory;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource(value = "classpath:application-mq.yml", factory = YamlPropertySourceFactory.class)
@Slf4j
public class MqAutoConfiguration {

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rt = new RabbitTemplate(connectionFactory);
        //当设置为 true 时，如果消息无法被交换机路由到任何队列，RabbitMQ 会通过 ReturnCallback 将消息退回给生产者。若为 false，则消息会被直接丢弃
        rt.setMandatory(true);

        /*
         * 确认回调函数 ConfirmCallback
         * 消息转发到交换机就会回调的函数，转发到队列是否成功都会被调用
         *  @param correlationData 消息编号之类
         * 	@param ack 是否成功，true 成功，false 失败
         * 	@param cause 失败的原因.
         */
        rt.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if(ack){
                    log.info("交换机接收消息编号：{} 成功！", cause, correlationData);
                }else{
                    log.error("交换机接收消息失败：{} 失败！原因：{}", correlationData, cause);
                }
            }
        });
        //退回回调函数ReturnsCallback是消息转发到队列失败回调的函数，成功则不会执行
        rt.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage rs) {
                log.error("消息id：{}", rs.getMessage().getMessageProperties().getHeader("spring_returned_message_correlation").toString());
                log.error("交换机：{}", rs.getExchange());
                log.error("应答码：{}", rs.getReplyCode());
                log.error("应答文本：{}", rs.getReplyText());
                log.error("绑定键：{}", rs.getRoutingKey());
                log.error("returnsCallback 返回消息：{}", rs.getMessage());
            }
        });
        return rt;
    }

}
